import numpy as np

def show_ls(ls):
    for i in ls:
        print(i)


class Point:
    def __init__(self, xy: tuple, y=None):
        if y == None:
            x, y = xy
        else:
            x = xy

        self.x = x
        self.y = y


class Shape:
    def __init__(self, points: np.ndarray):
        self.points = points
        self.center = points.sum(0)

    def getFarthestPointInDirection(self, d):
        return 1

if __name__ == '__main__':
    a_0 = [
        [4, 11],
        [4, 5],
        [9, 9],
    ]

    b_0 = [
        [5, 7],
        [7, 3],
        [10, 2],
        [12, 7],
    ]

    aa = np.array(a_0)
    bb = np.array(b_0)

    sa = Shape(aa)
    sb = Shape(bb)

    if 0:
        a = aa[0]
        b = bb[0]
        a - b

    if 0:
        c = np.array((-6, 9))
        a = np.array((4, 11))
        b = np.array((10, 2))
        b - a
        ab = np.array((-10, 7))
        ao = np.array((6, 9))

        np.dot(c, ab)

        d = np.array([0, 1])
        -d

    def getFarthestPointInDirection(aa, d):
        # 多边形aa在d方向上最远的点
        # d = np.array([2, 1])
        index_max = aa.dot(d).argmax()
        ret = aa[index_max]
        return ret

    def support(aa, bb, d):
        # 获得支持向量
        if not isinstance(d, np.ndarray):
            d = np.array(d)
        p1 = getFarthestPointInDirection(aa, d)
        p2 = getFarthestPointInDirection(bb, -d)
        p3 = p1 - p2
        return p3

    def conv_to_np(a, b):
        if not isinstance(a, np.ndarray) or isinstance(b, np.ndarray):
            a = np.array(a)
            b = np.array(b)
        return a, b

    def get_d_bycross(a, b):
        # 得到垂直于ab且反方向的法向量oc, 即为d
        a, b = conv_to_np(a, b)

        # 三维变二维
        ret_size = a.size
        if ret_size == 2:
            a = np.hstack([a, 0])
            b = np.hstack([b, 0])

        ab = b - a
        ao = 0 - a
        oc = np.cross(np.cross(ab, ao), ab)

        return oc[:-1]      # 变回2维

    if 1:
        # 实践
        class Simplex:
            def __init__(self):
                self.ls = []

            @property
            def a(self):
                if self.ls.__len__() < 3:
                    return self.ls[0]

                return self.ls[-3]

            @property
            def b(self):
                if self.ls.__len__() < 3:
                    if self.ls.__len__() < 2:
                        return None
                    return self.ls[1]

                return self.ls[-2]

            @property
            def c(self):
                if self.ls.__len__() < 3:
                    return None

                return self.ls[-1]

            def add(self, data):
                self.ls.append(data)
                if self.ls.__len__() > 3:
                    self.ls.pop(0)

            def info(self):
                show_ls(self.ls)

            def __repr__(self):
                return f'共{len(self.ls)}个, 元素:{self.ls}'

        simp = Simplex()

        a_center, b_center = (9, 5), (7.5, 6)
        a_center, b_center = conv_to_np(a_center, b_center)
        d = a_center - b_center

        # --- 初始化
        a = support(aa, bb, d)
        simp.add(a)
        simp.a

        d = -d
        b = support(aa, bb, d)
        simp.add(b)
        simp.b

        # 得到c, 计算完后c变成a, 旧的a被剔除
        d = get_d_bycross(a, b)
        d

        c = support(aa, bb, d)
        c
        simp.add(c)
        simp.c

        proj = c.dot(d)
        proj

        if proj < 0:
            print('False! 没有相交.')
        else:
            b = a if np.linalg.norm(a) < np.linalg.norm(b) else b       # 离原点更远的那个被抛弃
            a = c

            d = get_d_bycross(a, b)

        simp.info()     # 单纯形




        1
    pass
